﻿using Decoration.Comm;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Text;

namespace Decoration.Api.Comm
{
    public class JwtHelper
    {
        private static IConfiguration _configuration = ConfigurationHelper.GetConfiguration();
        private static JwtSecurityTokenHandler _jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
        public JwtHelper()
        {
            //_jwtSecurityTokenHandler = jwtSecurityTokenHandler;
        }
        /// <summary>
        /// 创建加密JwtToken
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static string CreateJwtToken<T>(T user)
        {
            var claimList = CreateClaimList(user);
            //  从 appsettings.json 中读取SecretKey
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]));
            // 从 appsettings.json 中读取Expired
            var expires = Convert.ToDouble(_configuration["JWT:Expired"]);
            //  选择加密算法
            var algorithm = SecurityAlgorithms.HmacSha256;
            // 生成Credentials
            var signingCredentials = new SigningCredentials(secretKey, algorithm);
            JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
               _configuration["JWT:Issuer"],     //Issuer
                _configuration["JWT:Audience"],   //Audience
                claims: claimList,
                DateTime.Now,                    //notBefore
                DateTime.Now.AddMinutes(expires),   //expires
                signingCredentials               //Credentials
                );
            string jwtToken = _jwtSecurityTokenHandler.WriteToken(jwtSecurityToken);
            return jwtToken;
        }
        private static TokenValidationParameters mTokenValidation = new TokenValidationParameters()
        {
            ValidateIssuerSigningKey = true,//是否验证签名,不验证的画可以篡改数据，不安全
            ValidateIssuer = true,
            ValidIssuer = _configuration["JWT:Issuer"],
            ValidateAudience = true,
            ValidAudience = _configuration["JWT:Audience"],
            ValidateLifetime = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]))
        };
        public static T GetToken<T>(string Token)
        {
            Type t = typeof(T);
            object objA = Activator.CreateInstance(t);


            var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);

            foreach (var item in b.Claims)
            {
                PropertyInfo _Property = t.GetProperty(item.Type);
                if (_Property != null && _Property.CanRead)
                {
                    //如果有其他类型需要再处理
                    if (_Property.PropertyType.Name == "Int32")
                    {
                        _Property.SetValue(objA, Int32.Parse(item.Value), null);
                    }
                    else
                    {
                        _Property.SetValue(objA, item.Value, null);
                    }

                }
            }
            return (T)objA;
        }
        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static ClaimsPrincipal ValidateToken(string token)
        {
            SecurityToken validatedToken;
            return _jwtSecurityTokenHandler.ValidateToken(token, mTokenValidation, out validatedToken);
        }
        /// <summary>
        /// 创建包含用户信息的CalimList
        /// </summary>
        /// <param name="authUser"></param>
        /// <returns></returns>
        private static List<Claim> CreateClaimList<T>(T authUser)
        {
            var Class = typeof(T);
            List<Claim> claimList = new List<Claim>();
            foreach (var item in Class.GetProperties())
            {
                claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser))));
            }
            return claimList;
        }
    }
}
